package com.atom.dbflow

import android.util.Log
import com.raizlabs.android.dbflow.config.FlowManager
import com.raizlabs.android.dbflow.kotlinextensions.async
import com.raizlabs.android.dbflow.sql.language.CursorResult
import com.raizlabs.android.dbflow.sql.language.OrderBy
import com.raizlabs.android.dbflow.sql.language.SQLOperator
import com.raizlabs.android.dbflow.sql.language.SQLite
import com.raizlabs.android.dbflow.sql.language.property.Property
import com.raizlabs.android.dbflow.structure.Model
import com.raizlabs.android.dbflow.structure.database.transaction.QueryTransaction
import com.raizlabs.android.dbflow.structure.database.transaction.Transaction
import com.saop.annotation.AopIntercept
import java.util.*

abstract class AbstractDbEntityHelper<T : Model> {

    abstract fun entity(): Class<T>

    // 数据保存
    fun save(
        models: Collection<T>,
        success: Transaction.Success? = null,
        error: Transaction.Error? = null,
        notice: Boolean = true,
        async: Boolean = true
    ) {
        if (models.isNotEmpty()) {
            FlowManager.getDatabase(DBFlowDatabase::class.java).beginTransactionAsync {
                val modelAdapter = FlowManager.getModelAdapter(entity())
                modelAdapter.saveAll(models)
            }.error { t, e ->
                error?.onError(t, e)
                if (notice) notify(-1, models, e)
            }.success { t ->
                success?.onSuccess(t)
                if (notice) notify(1, models)
            }.build().also {
                if (async) it.execute() else it.executeSync()
            }
        }
    }

    fun save(vararg models: T) {
        if (models.isNotEmpty()) {
            save(models.asList())
        }
    }

    // 数据更新
    fun update(
        models: Collection<T>,
        success: Transaction.Success? = null,
        error: Transaction.Error? = null,
        notice: Boolean = true,
        async: Boolean = true
    ) {
        if (models.isNotEmpty()) {
            FlowManager.getDatabase(DBFlowDatabase::class.java).beginTransactionAsync {
                FlowManager.getModelAdapter(entity()).updateAll(models)
            }.error { t, e ->
                error?.onError(t, e)
                if (notice) notify(-2, models, e)
            }.success { t ->
                success?.onSuccess(t)
                if (notice) notify(2, models)
            }.build().also {
                if (async) it.execute() else it.executeSync()
            }
        }
    }

    fun update(vararg models: T) {
        if (models.isNotEmpty()) {
            update(models.asList())
        }
    }


    fun update(
        set: List<SQLOperator>, where: List<SQLOperator>,
        success: Transaction.Success? = null,
        error: Transaction.Error? = null
    ) {
        SQLite
            .update(entity())
            .set(*set.toTypedArray())
            .where(*where.toTypedArray())
            .async()
            .success(success)
            .error(error)
            .execute()
        SQLite.insert(entity()).columnValues(*set.toTypedArray()).execute()
    }

    fun update(
        set: List<SQLOperator>, where: List<SQLOperator>
    ): Long {
        return SQLite
            .update(entity())
            .set(*set.toTypedArray())
            .where(*where.toTypedArray())
            .executeUpdateDelete()
    }


    // 数据删除
    fun delete(
        models: Collection<T>,
        success: Transaction.Success? = null,
        error: Transaction.Error? = null,
        notice: Boolean = true,
        async: Boolean = true
    ) {
        if (models.isNotEmpty()) {
            FlowManager.getDatabase(DBFlowDatabase::class.java).beginTransactionAsync {
                FlowManager.getModelAdapter(entity()).deleteAll(models)
            }.error { t, e ->
                error?.onError(t, e)
                if (notice) notify(-3, models, e)
            }.success { t ->
                success?.onSuccess(t)
                if (notice) notify(3, models)
            }.build().also {
                if (async) it.execute() else it.executeSync()
            }
        }
    }

    fun delete(vararg models: T) {
        if (models.isNotEmpty()) {
            delete(models.asList())
        }
    }

    fun delete(
        where: List<SQLOperator>,
        success: Transaction.Success? = null,
        error: Transaction.Error? = null
    ) {
        SQLite.delete(entity())
            .where(*where.toTypedArray())
            .async()
            .success(success)
            .error(error)
            .execute()
    }

    fun delete(
        where: List<SQLOperator>
    ): Long {
        return SQLite.delete(entity())
            .where(*where.toTypedArray()).executeUpdateDelete()
    }

    fun getByCallback(
        sqlOperator: SQLOperator,
        orderBy: OrderBy,
        limit: Int,
        queryCallback: QueryTransaction.QueryResultCallback<T>
    ) {
        SQLite.select().from(entity()).where(sqlOperator).orderBy(orderBy).limit(limit).async()
            .queryResultCallback(queryCallback).execute()
    }

    // 数据查询
    fun getSingle(uuid: String): T? {
        return SQLite.select().from(entity())
            .where(Property<String>(entity(), "id").eq(uuid))
            .querySingle()
    }

    fun getSingle(sqlOperator: SQLOperator): T? {
        return SQLite.select().from(entity())
            .where(sqlOperator)
            .querySingle()
    }

    fun getSingleByCallback(
        sqlOperator: SQLOperator,
        querySingleCallback: QueryTransaction.QueryResultSingleCallback<T>
    ) {
        SQLite.select().from(entity()).where(sqlOperator)
            .async().querySingleResultCallback(querySingleCallback).execute()
    }

    fun getCollection(sqlOperator: SQLOperator): List<T>? {
        return SQLite.select().from(entity()).where(sqlOperator)
            .queryList()
    }

    fun getCollection(sqlOperator: SQLOperator, orderBy: OrderBy, limit: Int): List<T>? {
        return SQLite.select().from(entity())
            .where(sqlOperator).orderBy(orderBy).limit(limit)
            .queryList()
    }

    fun getCollectionByCallback(
        sqlOperator: SQLOperator,
        queryListCallback: QueryTransaction.QueryResultListCallback<T>
    ) {
        SQLite.select().from(entity()).where(sqlOperator).async()
            .queryListResultCallback(queryListCallback).execute()
    }

    fun getCollectionByCallback(
        sqlOperator: SQLOperator,
        orderBy: OrderBy,
        limit: Int,
        queryListCallback: QueryTransaction.QueryResultListCallback<T>
    ) {
        SQLite.select().from(entity()).where(sqlOperator).orderBy(orderBy).limit(limit).async()
            .queryListResultCallback(queryListCallback)
            .execute()
    }

    private fun notify(int: Int, type: Collection<T>?, e: Throwable? = null) {
        when (int) {
            1 -> Log.e("DBFlowActivity", " --> 新增 \n ${type?.size} \n $type  ")
            2 -> Log.e("DBFlowActivity", " --> 更新 \n ${type?.size} \n $type  ")
            3 -> Log.e("DBFlowActivity", " --> 删除 \n ${type?.size} \n $type  ")

            -1 -> Log.e("DBFlowActivity", " --> 新增异常 \n ${e?.localizedMessage} \n $e  ")
            -2 -> Log.e("DBFlowActivity", " --> 更新异常 \n ${e?.localizedMessage} \n $e  ")
            -3 -> Log.e("DBFlowActivity", " --> 删除异常 \n ${e?.localizedMessage} \n $e  ")
        }
    }
}